import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../common/models/server_model.dart';
import '../../../common/services/server_service.dart';
import '../../../common/utils/index.dart';

/// 文件信息
class FileInfo {
  final String name;
  final String path;
  final bool isDirectory;
  final String size;
  final String permissions;
  final String owner;
  final String modified;

  FileInfo({
    required this.name,
    required this.path,
    required this.isDirectory,
    required this.size,
    required this.permissions,
    required this.owner,
    required this.modified,
  });

  /// 从 ls -lh 输出解析
  factory FileInfo.fromLsLine(String line, String currentPath) {
    // drwxr-xr-x 5 root root 4.0K Nov  2 21:00 docker
    // -rw-r--r-- 1 root root  156 Nov  2 20:00 test.txt
    final parts = line.split(RegExp(r'\s+'));
    if (parts.length < 9) {
      return FileInfo(
        name: line,
        path: currentPath,
        isDirectory: false,
        size: '',
        permissions: '',
        owner: '',
        modified: '',
      );
    }

    final permissions = parts[0];
    final owner = parts[2];
    final size = parts[4];
    final modified = '${parts[5]} ${parts[6]} ${parts[7]}';
    final name = parts.sublist(8).join(' ');

    return FileInfo(
      name: name,
      path: '$currentPath/$name',
      isDirectory: permissions.startsWith('d'),
      size: size,
      permissions: permissions,
      owner: owner,
      modified: modified,
    );
  }
}

class ServerFilesController extends GetxController {
  final ServerService _serverService = Get.find<ServerService>();
  late final String serverId;

  Rx<ServerModel?> server = Rx<ServerModel?>(null);
  RxList<FileInfo> files = <FileInfo>[].obs;
  RxString currentPath = '/'.obs;
  RxList<String> pathHistory = <String>[].obs;

  RxBool isLoading = false.obs;
  RxString errorMessage = ''.obs;

  // 状态监听订阅
  StreamSubscription<ServerModel>? _stateSubscription;

  @override
  void onInit() {
    super.onInit();
    debugPrint('🎬 ServerFilesController: onInit');

    serverId = Get.parameters['id'] ?? '';
    debugPrint('   服务器ID: $serverId');

    if (serverId.isEmpty) {
      debugPrint('❌ ServerFilesController: 服务器 ID 为空');
      LoadingUtil.error('服务器 ID 无效');
      Get.back();
      return;
    }

    _loadServer();
    _listenToServerStateChanges();
  }

  /// 监听服务器状态变化
  void _listenToServerStateChanges() {
    debugPrint('👂 ServerFilesController: 开始监听服务器状态变化');
    _stateSubscription = _serverService.watchServer(serverId).listen((updatedServer) {
      debugPrint('📢 ServerFilesController: 收到服务器状态更新 - ${updatedServer.name}');
      server.value = updatedServer;
    });
  }

  Future<void> _loadServer() async {
    debugPrint('📋 ServerFilesController: 加载服务器信息 - ID: $serverId');

    server.value = _serverService.getServer(serverId);
    if (server.value == null) {
      debugPrint('❌ ServerFilesController: 服务器不存在');
      LoadingUtil.error('服务器不存在');
      Get.back();
      return;
    }

    debugPrint('✅ ServerFilesController: 服务器信息加载成功');

    // 如果已连接，加载文件列表
    if (_serverService.isConnected(serverId)) {
      await loadFiles();
    }
  }

  /// 加载文件列表
  Future<void> loadFiles() async {
    if (!_serverService.isConnected(serverId)) {
      LoadingUtil.error('未连接到服务器');
      return;
    }

    isLoading.value = true;
    errorMessage.value = '';

    try {
      debugPrint('📁 ServerFilesController: 加载文件列表 - ${currentPath.value}');
      final client = _serverService.getClient(serverId);
      if (client == null) {
        throw Exception('未连接到服务器');
      }

      // 使用 ls -lh 命令获取文件列表
      final result = await client.run('ls -lh "${currentPath.value}" 2>&1');
      final output = utf8.decode(result);

      if (output.contains('cannot access') || output.contains('No such file')) {
        throw Exception('无法访问该目录');
      }

      final lines = output.split('\n')
          .where((line) => line.trim().isNotEmpty)
          .skip(1) // 跳过 total 行
          .toList();

      files.value = lines
          .where((line) => !line.startsWith('total'))
          .map((line) => FileInfo.fromLsLine(line, currentPath.value))
          .where((file) => file.name != '.' && file.name != '..')
          .toList();

      // 排序：目录在前，文件在后
      files.sort((a, b) {
        if (a.isDirectory && !b.isDirectory) return -1;
        if (!a.isDirectory && b.isDirectory) return 1;
        return a.name.compareTo(b.name);
      });

      debugPrint('✅ ServerFilesController: 加载了 ${files.length} 个文件/目录');
    } catch (e) {
      debugPrint('❌ ServerFilesController: 加载文件失败 - $e');
      errorMessage.value = '加载文件失败: $e';
      LoadingUtil.error('加载文件失败: $e');
    } finally {
      isLoading.value = false;
    }
  }

  /// 进入目录
  void enterDirectory(FileInfo file) {
    if (!file.isDirectory) return;

    pathHistory.add(currentPath.value);
    currentPath.value = file.path;
    loadFiles();
  }

  /// 返回上级目录
  void goBack() {
    if (pathHistory.isNotEmpty) {
      // 如果有历史记录，返回到历史路径
      currentPath.value = pathHistory.removeLast();
    } else {
      // 如果没有历史记录，解析当前路径的上级目录
      final parentPath = _getParentPath(currentPath.value);
      if (parentPath != null) {
        currentPath.value = parentPath;
      } else {
        // 已经在根目录，无法再返回
        LoadingUtil.info('已在根目录');
        return;
      }
    }
    loadFiles();
  }

  /// 获取父级路径
  String? _getParentPath(String path) {
    if (path == '/') return null; // 根目录没有父级
    
    // 移除末尾的斜杠
    if (path.endsWith('/') && path.length > 1) {
      path = path.substring(0, path.length - 1);
    }
    
    final lastSlashIndex = path.lastIndexOf('/');
    if (lastSlashIndex == 0) {
      return '/'; // 父级是根目录
    } else if (lastSlashIndex > 0) {
      return path.substring(0, lastSlashIndex);
    }
    return null;
  }

  /// 跳转到指定路径
  void goToPath(String path) {
    if (path.isEmpty || path == currentPath.value) return;

    // 不添加到历史记录，直接跳转（用于快捷目录）
    currentPath.value = path;
    pathHistory.clear(); // 清空历史记录
    loadFiles();
  }

  /// 刷新
  Future<void> refresh() => loadFiles();

  /// 删除文件/目录
  Future<void> deleteFile(FileInfo file) async {
    final confirmed = await Get.dialog<bool>(
      AlertDialog(
        title: const Text('确认删除', style: TextStyle(fontSize: 15)),
        content: Text(
          '确定要删除 "${file.name}" 吗？${file.isDirectory ? '\n此操作将删除目录及其所有内容！' : ''}',
          style: const TextStyle(fontSize: 12),
        ),
        actions: [
          TextButton(
            onPressed: () => Get.back(result: false),
            child: const Text('取消'),
          ),
          TextButton(
            onPressed: () => Get.back(result: true),
            style: TextButton.styleFrom(foregroundColor: Colors.red),
            child: const Text('删除'),
          ),
        ],
      ),
    );

    if (confirmed == true) {
      try {
        LoadingUtil.show('删除中...');
        final client = _serverService.getClient(serverId);
        if (client == null) {
          throw Exception('未连接到服务器');
        }

        final cmd = file.isDirectory
            ? 'rm -rf "${file.path}"'
            : 'rm -f "${file.path}"';

        await client.run(cmd);
        LoadingUtil.success('删除成功');
        await loadFiles();
      } catch (e) {
        LoadingUtil.error('删除失败: $e');
      } finally {
        LoadingUtil.dismiss();
      }
    }
  }

  /// 创建目录
  Future<void> createDirectory() async {
    final controller = TextEditingController();
    final result = await Get.dialog<String>(
      AlertDialog(
        title: const Text('创建目录', style: TextStyle(fontSize: 15)),
        content: TextField(
          controller: controller,
          decoration: const InputDecoration(
            hintText: '请输入目录名称',
            hintStyle: TextStyle(fontSize: 12),
          ),
          style: const TextStyle(fontSize: 13),
        ),
        actions: [
          TextButton(
            onPressed: () => Get.back(),
            child: const Text('取消'),
          ),
          ElevatedButton(
            onPressed: () => Get.back(result: controller.text),
            child: const Text('创建'),
          ),
        ],
      ),
    );

    if (result != null && result.isNotEmpty) {
      try {
        LoadingUtil.show('创建中...');
        final client = _serverService.getClient(serverId);
        if (client == null) {
          throw Exception('未连接到服务器');
        }

        await client.run('mkdir -p "${currentPath.value}/$result"');
        LoadingUtil.success('创建成功');
        await loadFiles();
      } catch (e) {
        LoadingUtil.error('创建失败: $e');
      } finally {
        LoadingUtil.dismiss();
      }
    }
  }

  /// 读取文件内容
  Future<String?> readFileContent(FileInfo file) async {
    if (file.isDirectory) {
      LoadingUtil.error('无法读取目录');
      return null;
    }

    try {
      LoadingUtil.show('读取中...');
      final client = _serverService.getClient(serverId);
      if (client == null) {
        throw Exception('未连接到服务器');
      }

      // 使用 cat 命令读取文件内容
      final result = await client.run('cat "${file.path}" 2>&1');
      final content = utf8.decode(result);

      // 检查是否是二进制文件或读取错误
      if (content.contains('binary file') || content.contains('cannot open')) {
        throw Exception('无法读取该文件（可能是二进制文件）');
      }

      LoadingUtil.dismiss();
      return content;
    } catch (e) {
      LoadingUtil.error('读取失败: $e');
      return null;
    }
  }

  /// 保存文件内容
  Future<bool> saveFileContent(FileInfo file, String content) async {
    try {
      LoadingUtil.show('保存中...');
      final client = _serverService.getClient(serverId);
      if (client == null) {
        throw Exception('未连接到服务器');
      }

      // 转义特殊字符和换行符
      final escapedContent = content
          .replaceAll('\\', '\\\\')
          .replaceAll('"', '\\"')
          .replaceAll('\$', '\\\$')
          .replaceAll('`', '\\`');

      // 使用 echo 和重定向保存文件（适合小文件）
      // 对于大文件，使用 cat > 方式
      final result = await client.run('cat > "${file.path}" << "EOF"\n$content\nEOF');
      
      LoadingUtil.success('保存成功');
      return true;
    } catch (e) {
      LoadingUtil.error('保存失败: $e');
      return false;
    } finally {
      LoadingUtil.dismiss();
    }
  }

  /// 判断是否为文本文件
  bool isTextFile(String filename) {
    final textExtensions = [
      'txt', 'log', 'md', 'yaml', 'yml', 'json', 'xml', 'html', 'htm',
      'css', 'js', 'ts', 'jsx', 'tsx', 'vue', 'php', 'py', 'java', 'c',
      'cpp', 'h', 'hpp', 'go', 'rs', 'dart', 'sh', 'bash', 'zsh',
      'conf', 'config', 'ini', 'env', 'properties', 'sql', 'dockerfile',
      'gitignore', 'gradle', 'cmake', 'makefile', 'toml',
    ];

    final extension = filename.split('.').last.toLowerCase();
    return textExtensions.contains(extension) || 
           filename.toLowerCase() == 'dockerfile' ||
           filename.toLowerCase() == 'makefile' ||
           filename.startsWith('.');
  }

  /// 重命名
  Future<void> renameFile(FileInfo file) async {
    final controller = TextEditingController(text: file.name);
    final result = await Get.dialog<String>(
      AlertDialog(
        title: const Text('重命名', style: TextStyle(fontSize: 15)),
        content: TextField(
          controller: controller,
          decoration: const InputDecoration(
            hintText: '请输入新名称',
            hintStyle: TextStyle(fontSize: 12),
          ),
          style: const TextStyle(fontSize: 13),
        ),
        actions: [
          TextButton(
            onPressed: () => Get.back(),
            child: const Text('取消'),
          ),
          ElevatedButton(
            onPressed: () => Get.back(result: controller.text),
            child: const Text('确定'),
          ),
        ],
      ),
    );

    if (result != null && result.isNotEmpty && result != file.name) {
      try {
        LoadingUtil.show('重命名中...');
        final client = _serverService.getClient(serverId);
        if (client == null) {
          throw Exception('未连接到服务器');
        }

        final newPath = '${currentPath.value}/$result';
        await client.run('mv "${file.path}" "$newPath"');
        LoadingUtil.success('重命名成功');
        await loadFiles();
      } catch (e) {
        LoadingUtil.error('重命名失败: $e');
      } finally {
        LoadingUtil.dismiss();
      }
    }
  }

  @override
  void onClose() {
    debugPrint('🔚 ServerFilesController: onClose');
    _stateSubscription?.cancel();
    super.onClose();
  }
}

